package main

import (
	"fmt"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"sync"
	"time"

	. "github.com/soekchl/myUtils"
)

/*

	https://www.godamanga.com/chapterlist/wuliandianfeng-pikapi/

	https://www.godamanga.com/manga/wuliandianfeng-pikapi/
	https://www.godamanga.com/manga/wuliandianfeng-pikapi/0_3096/
	https://w3wy1.godamanga.online/scomic/wuliandianfeng-pikapi/0/3092-2qh7/7.jpg
	https://w3wy1.godamanga.online/scomic/wuliandianfeng-pikapi/0/3092-2qh7/2.jpg
	https://w3wy1.godamanga.online/scomic/wuliandianfeng-pikapi/0/3092-2qh7/6.jpg


*/

const (
	godaStartKey = `data-src="`
	godaStopKey  = `"`
)

type GodaStruct struct {
	Chapterid   string
	Chaptername string
}

func (g *GodaStruct) run() {
	Notice("Goda")
	switch *outPutMod {
	case 1, 2:
		Notice("Goda 读取json只生成reqList")
		g.getGodaReqList()
		outPutJson()
		Notice("Goda 已生成json")
	default:
		// 下载漫画
		g.downloadList()
	}
}

func (g *GodaStruct) downloadList() {
	Notice("开始下载漫画")

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	go func() {
		<-c
		errDownMutex.Lock()
		if len(errDown) > 1 {
			fmt.Printf("发生异常的数据：%v", errDown)
		}
		errDownMutex.Unlock()

		str := ""
		m := 0
		for i := info.StartNum; i < info.StartNum+len(info.ReqList); i++ {
			okDownMutex.Lock()
			if !okDown[i] {
				str += fmt.Sprint(i, ",")
				m++
			}
			okDownMutex.Unlock()
		}
		Noticef("总共：%v 未完成=%v 列表=%v", len(info.ReqList), m, str)
		os.Exit(0)
	}()

	slc := time.Duration(1)
	for n, v := range info.ReqList {
		if n&1 == 0 {
			continue
		}
		k := n / 2
		if len(v) < 10 {
			okDownMutex.Lock()
			okDown[info.StartNum+k] = true
			okDownMutex.Unlock()
			Notice(info.StartNum+k, " 不下载跳过")
			continue
		}
		wg.Add(1)
		go func(idx int, u string) {
			defer wg.Done()
			for !g.getOne(idx, u) {
				time.Sleep(time.Second)
			}

		}(k+info.StartNum, info.HeaderUrl+v)

		time.Sleep(time.Second / 1000 * info.Sleeptime * slc)
		slc += 1
		if slc > 30 {
			slc = 30
		}
	}
	wg.Wait()

	checkErrorDown()
}

// 获取一话完整图片
func (g *GodaStruct) getOne(m int, urlReq string) (errFlag bool) {
	defer func() {
		okDownMutex.Lock()
		okDown[m] = true
		okDownMutex.Unlock()
		Notice("\n\t", m, " over", recover())
	}()

	code, body, err := httpReq(urlReq, "get", nil, make(url.Values)) // 请求主网址内容
	if err != nil {
		Error(err)
		return
	}
	// data-lazy-src="
	if code != 200 {
		if len(body) > 1024 {
			Errorf("code=%v url=%v body=%s", code, urlReq, body[:1024])
		} else {
			Errorf("code=%v url=%v body=%s", code, urlReq, body)
		}

		return
	}

	list := g.getImages(body) // 从主网址中分离目标图表
	Noticef("漫画=%v 个数=%v", m, len(list))
	all += len(list)
	dir := fmt.Sprint("./comic/", m, "/")
	err = os.MkdirAll(dir, os.ModePerm)
	if err != nil {
		Error(err)
		return
	}
	n := 1
	var wg sync.WaitGroup
	for _, v := range list { // 一个一个下载
		wg.Add(1)
		go func(n int, v string) {
			defer wg.Done()
			_, err = downloadImages(v, fmt.Sprintf("%vIMGE_%v.jpeg", dir, n))
			if err != nil {
				Errorf("m=%v n=%v err=%v", m, n, err)
				errDownMutex.Lock()
				errDown[m] = append(errDown[m], tempStruct{
					url:      v,
					fileName: fmt.Sprintf("%vIMGE_%v.jpg", dir, n),
				})
				errDownMutex.Unlock()
			}
		}(n, v)
		n++
		time.Sleep(time.Second / 1000 * info.Sleeptime)
	}
	wg.Wait()
	return true
}

// 从读取出来的 html中查找 chapterImages = [] 内容
func (g *GodaStruct) getImages(body string) (imgList []string) {
	for {
		str, stopIndex := getString(body, [2]string{godaStartKey, godaStopKey})
		if len(str) < 1 {
			break
		}

		imgList = append(imgList, str)
		body = body[stopIndex:] // 截断
	}

	return
}

// 通用 有数字就转换
func (g *GodaStruct) getGodaReqList() {
	href = [2]string{`<a href="`, `"`}
	span = [2]string{` truncate`, `<span`}

	id := ""
	tmps := strings.Split(info.ComicHome, "/")
	if len(tmps) > 1 {
		id = tmps[len(tmps)-2]
	}
	Warnf("id = %v", id)

	code, body, err := httpReq(info.ComicHome, "get", nil, make(url.Values)) // 请求主网址内容
	if err != nil {
		Error("getReqList " + err.Error())
		os.Exit(1)

	}

	if code != 200 {
		Error(fmt.Sprintf("getReqList  code=%v url=%v  err=%s", code, info.ComicHome, body))
		os.Exit(1)
	}

	// 跳到关键字
	n := strings.Index(body, info.Key)
	if n < 1 {
		Error("关键字未找到", info.Key)
		time.Sleep(time.Second * 3)
		Notice(body)
		os.Exit(1)
	}
	body = body[n:]
	var class []string
	var hrefs []string
	var list []string

	// Notice(body)

	for {
		hrefStr, _ := getString(body, href)
		spanStr, stopIndex := getString(body, span)
		// 检查里面 有 href 和 span  就截取 保存
		Noticef("_%v_%v_ ", hrefStr, spanStr)
		if len(hrefStr) < 1 || len(spanStr) < 1 {
			if len(list) < 1 {
				Warnf("hrefStr=%v spanStr=%v stopIndex=%v", hrefStr, spanStr, stopIndex)
			}
			break
		}

		hrefs = append(hrefs, hrefStr)
		class = append(class, spanStr)

		if *outPutMod == 2 { // 反转
			list = append([]string{hrefStr}, list...)
			list = append([]string{spanStr}, list...)
		} else {
			list = append(list, spanStr)
			list = append(list, hrefStr)
		}

		body = body[stopIndex:] // 截断
	}

	info.ReqList = list
	// Notice(list)
	// Notice(hrefs)
	// Notice(class)
	mm := make(map[int]string)
	mms := make(map[int]string)
	n = 0
	max := 0
	var reqlist []string
	var haveLast []string

	// 检查是否可以数字化
	for i := 0; i < len(class); i++ {
		num := getNumberToStr(class[i])
		if num > max { // 查找最大值
			max = num
		}
		if num == -2 {
			haveLast = append(haveLast, class[i])
			haveLast = append(haveLast, hrefs[i])
		} else {
			mms[num] = class[i]
			mm[num] = hrefs[i]
		}
	}
	Noticef("max=%v class=%v mm=%v", max, len(class), len(mm))
	var nh []int

	// 数字化
	for k := 1; k <= max; k++ {
		i := k
		reqlist = append(reqlist, mms[i])
		if len(mm[i]) > 0 {
			reqlist = append(reqlist, mm[i])
		} else {
			reqlist = append(reqlist, fmt.Sprint(i))
			n++
			nh = append(nh, i)
		}
	}

	Noticef("info.IfUseNum=%v 总共：%v 缺少：%v 缺少详情：%v", info.IfUseNum, len(reqlist)/2, n, nh)
	if info.IfUseNum {
		info.ReqList = reqlist
	}
}
